﻿if (!function () { }.bind) {

    Function.prototype.bind =
     function (context) {
         var method = this,
         slice = Array.prototype.slice,
         args = slice.call(arguments, 1),
         innerArgs, finalArgs;
         return function () {
             innerArgs = slice.call(arguments);
             finalArgs = args.concat(innerArgs)
             return method.call(context, finalArgs);
         };
     };
}

(function (window, undefined, perfix) {

    var Sizzle = (function () {
        var cachedruns,
        assertGetIdNotName,
        Expr,
        getText,
        isXML,
        contains,
        compile,
        sortOrder,
        hasDuplicate,
        outermostContext,

        baseHasDuplicate = true,
        strundefined = "undefined",

        expando = ("sizcache" + Math.random()).replace(".", ""),

        Token = String,
        document = window.document,
        docElem = document.documentElement,
        dirruns = 0,
        done = 0,
        pop = [].pop,
        push = [].push,
        slice = [].slice,
        // Use a stripped-down indexOf if a native one is unavailable
        indexOf = [].indexOf || function (elem) {
            var i = 0,
                len = this.length;
            for (; i < len; i++) {
                if (this[i] === elem) {
                    return i;
                }
            }
            return -1;
        },

        // Augment a function for special use by Sizzle
        markFunction = function (fn, value) {
            fn[expando] = value == null || value;
            return fn;
        },

        createCache = function () {
            var cache = {},
                keys = [];

            return markFunction(function (key, value) {
                // Only keep the most recent entries
                if (keys.push(key) > Expr.cacheLength) {
                    delete cache[keys.shift()];
                }

                return (cache[key] = value);
            }, cache);
        },

        classCache = createCache(),
        tokenCache = createCache(),
        compilerCache = createCache(),

        // Regex

        // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
        whitespace = "[\\x20\\t\\r\\n\\f]",
        // http://www.w3.org/TR/css3-syntax/#characters
        characterEncoding = "(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",

        // Loosely modeled on CSS identifier characters
        // An unquoted value should be a CSS identifier (http://www.w3.org/TR/css3-selectors/#attribute-selectors)
        // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
        identifier = characterEncoding.replace("w", "w#"),

        // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors
        operators = "([*^$|!~]?=)",
        attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +
            "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",

        // Prefer arguments not in parens/brackets,
        //   then attribute selectors and non-pseudos (denoted by :),
        //   then anything else
        // These preferences are here to reduce the number of selectors
        //   needing tokenize in the PSEUDO preFilter
        pseudos = ":(" + characterEncoding + ")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:" + attributes + ")|[^:]|\\\\.)*|.*))\\)|)",

        // For matchExpr.POS and matchExpr.needsContext
        pos = ":(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace +
            "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)",

        // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
        rtrim = new RegExp("^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g"),

        rcomma = new RegExp("^" + whitespace + "*," + whitespace + "*"),
        rcombinators = new RegExp("^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*"),
        rpseudo = new RegExp(pseudos),

        // Easily-parseable/retrievable ID or TAG or CLASS selectors
        rquickExpr = /^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,

        rnot = /^:not/,
        rsibling = /[\x20\t\r\n\f]*[+~]/,
        rendsWithNot = /:not\($/,

        rheader = /h\d/i,
        rinputs = /input|select|textarea|button/i,

        rbackslash = /\\(?!\\)/g,

        matchExpr = {
            "ID": new RegExp("^#(" + characterEncoding + ")"),
            "CLASS": new RegExp("^\\.(" + characterEncoding + ")"),
            "NAME": new RegExp("^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]"),
            "TAG": new RegExp("^(" + characterEncoding.replace("w", "w*") + ")"),
            "ATTR": new RegExp("^" + attributes),
            "PSEUDO": new RegExp("^" + pseudos),
            "POS": new RegExp(pos, "i"),
            "CHILD": new RegExp("^:(only|nth|first|last)-child(?:\\(" + whitespace +
                "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
                "*(\\d+)|))" + whitespace + "*\\)|)", "i"),
            // For use in libraries implementing .is()
            "needsContext": new RegExp("^" + whitespace + "*[>+~]|" + pos, "i")
        },

        // Support

        // Used for testing something on an element
        assert = function (fn) {
            var div = document.createElement("div");

            try {
                return fn(div);
            } catch (e) {
                return false;
            } finally {
                // release memory in IE
                div = null;
            }
        },

        // Check if getElementsByTagName("*") returns only elements
        assertTagNameNoComments = assert(function (div) {
            div.appendChild(document.createComment(""));
            return !div.getElementsByTagName("*").length;
        }),

        // Check if getAttribute returns normalized href attributes
        assertHrefNotNormalized = assert(function (div) {
            div.innerHTML = "<a href='#'></a>";
            return div.firstChild && typeof div.firstChild.getAttribute !== strundefined &&
                div.firstChild.getAttribute("href") === "#";
        }),

        // Check if attributes should be retrieved by attribute nodes
        assertAttributes = assert(function (div) {
            div.innerHTML = "<select></select>";
            var type = typeof div.lastChild.getAttribute("multiple");
            // IE8 returns a string for some attributes even when not present
            return type !== "boolean" && type !== "string";
        }),

        // Check if getElementsByClassName can be trusted
        assertUsableClassName = assert(function (div) {
            // Opera can't find a second classname (in 9.6)
            div.innerHTML = "<div class='hidden e'></div><div class='hidden'></div>";
            if (!div.getElementsByClassName || !div.getElementsByClassName("e").length) {
                return false;
            }

            // Safari 3.2 caches class attributes and doesn't catch changes
            div.lastChild.className = "e";
            return div.getElementsByClassName("e").length === 2;
        }),

        // Check if getElementById returns elements by name
        // Check if getElementsByName privileges form controls or returns elements by ID
        assertUsableName = assert(function (div) {
            // Inject content
            div.id = expando + 0;
            div.innerHTML = "<a name='" + expando + "'></a><div name='" + expando + "'></div>";
            docElem.insertBefore(div, docElem.firstChild);

            // Test
            var pass = document.getElementsByName &&
                // buggy browsers will return fewer than the correct 2
                document.getElementsByName(expando).length === 2 +
                // buggy browsers will return more than the correct 0
                document.getElementsByName(expando + 0).length;
            assertGetIdNotName = !document.getElementById(expando);

            // Cleanup
            docElem.removeChild(div);

            return pass;
        });

        // If slice is not available, provide a backup
        try {
            slice.call(docElem.childNodes, 0)[0].nodeType;
        } catch (e) {
            slice = function (i) {
                var elem,
                    results = [];
                for (; (elem = this[i]) ; i++) {
                    results.push(elem);
                }
                return results;
            };
        }

        function Sizzle(selector, context, results, seed) {
            results = results || [];
            context = context || document;
            var match, elem, xml, m,
                nodeType = context.nodeType;

            if (!selector || typeof selector !== "string") {
                return results;
            }

            if (nodeType !== 1 && nodeType !== 9) {
                return [];
            }

            xml = isXML(context);

            if (!xml && !seed) {
                if ((match = rquickExpr.exec(selector))) {
                    // Speed-up: Sizzle("#ID")
                    if ((m = match[1])) {
                        if (nodeType === 9) {
                            elem = context.getElementById(m);
                            // Check parentNode to catch when Blackberry 4.6 returns
                            // nodes that are no longer in the document #6963
                            if (elem && elem.parentNode) {
                                // Handle the case where IE, Opera, and Webkit return items
                                // by name instead of ID
                                if (elem.id === m) {
                                    results.push(elem);
                                    return results;
                                }
                            } else {
                                return results;
                            }
                        } else {
                            // Context is not a document
                            if (context.ownerDocument && (elem = context.ownerDocument.getElementById(m)) &&
                                contains(context, elem) && elem.id === m) {
                                results.push(elem);
                                return results;
                            }
                        }

                        // Speed-up: Sizzle("TAG")
                    } else if (match[2]) {
                        push.apply(results, slice.call(context.getElementsByTagName(selector), 0));
                        return results;

                        // Speed-up: Sizzle(".CLASS")
                    } else if ((m = match[3]) && assertUsableClassName && context.getElementsByClassName) {
                        push.apply(results, slice.call(context.getElementsByClassName(m), 0));
                        return results;
                    }
                }
            }

            // All others
            return select(selector.replace(rtrim, "$1"), context, results, seed, xml);
        }

        Sizzle.matches = function (expr, elements) {
            return Sizzle(expr, null, null, elements);
        };

        Sizzle.matchesSelector = function (elem, expr) {
            return Sizzle(expr, null, null, [elem]).length > 0;
        };

        // Returns a function to use in pseudos for input types
        function createInputPseudo(type) {
            return function (elem) {
                var name = elem.nodeName.toLowerCase();
                return name === "input" && elem.type === type;
            };
        }

        // Returns a function to use in pseudos for buttons
        function createButtonPseudo(type) {
            return function (elem) {
                var name = elem.nodeName.toLowerCase();
                return (name === "input" || name === "button") && elem.type === type;
            };
        }

        // Returns a function to use in pseudos for positionals
        function createPositionalPseudo(fn) {
            return markFunction(function (argument) {
                argument = +argument;
                return markFunction(function (seed, matches) {
                    var j,
                        matchIndexes = fn([], seed.length, argument),
                        i = matchIndexes.length;

                    // Match elements found at the specified indexes
                    while (i--) {
                        if (seed[(j = matchIndexes[i])]) {
                            seed[j] = !(matches[j] = seed[j]);
                        }
                    }
                });
            });
        }

        /**
         * Utility function for retrieving the text value of an array of DOM nodes
         * @param {Array|Element} elem
         */
        getText = Sizzle.getText = function (elem) {
            var node,
                ret = "",
                i = 0,
                nodeType = elem.nodeType;

            if (nodeType) {
                if (nodeType === 1 || nodeType === 9 || nodeType === 11) {
                    // Use textContent for elements
                    // innerText usage removed for consistency of new lines (see #11153)
                    if (typeof elem.textContent === "string") {
                        return elem.textContent;
                    } else {
                        // Traverse its children
                        for (elem = elem.firstChild; elem; elem = elem.nextSibling) {
                            ret += getText(elem);
                        }
                    }
                } else if (nodeType === 3 || nodeType === 4) {
                    return elem.nodeValue;
                }
                // Do not include comment or processing instruction nodes
            } else {

                // If no nodeType, this is expected to be an array
                for (; (node = elem[i]) ; i++) {
                    // Do not traverse comment nodes
                    ret += getText(node);
                }
            }
            return ret;
        };

        isXML = Sizzle.isXML = function (elem) {
            // documentElement is verified for cases where it doesn't yet exist
            // (such as loading iframes in IE - #4833)
            var documentElement = elem && (elem.ownerDocument || elem).documentElement;
            return documentElement ? documentElement.nodeName !== "HTML" : false;
        };

        // Element contains another
        contains = Sizzle.contains = docElem.contains ?
            function (a, b) {
                var adown = a.nodeType === 9 ? a.documentElement : a,
                    bup = b && b.parentNode;
                return a === bup || !!(bup && bup.nodeType === 1 && adown.contains && adown.contains(bup));
            } :
            docElem.compareDocumentPosition ?
            function (a, b) {
                return b && !!(a.compareDocumentPosition(b) & 16);
            } :
            function (a, b) {
                while ((b = b.parentNode)) {
                    if (b === a) {
                        return true;
                    }
                }
                return false;
            };

        Sizzle.attr = function (elem, name) {
            var val,
                xml = isXML(elem);

            if (!xml) {
                name = name.toLowerCase();
            }
            if ((val = Expr.attrHandle[name])) {
                return val(elem);
            }
            if (xml || assertAttributes) {
                return elem.getAttribute(name);
            }
            val = elem.getAttributeNode(name);
            return val ?
                typeof elem[name] === "boolean" ?
                    elem[name] ? name : null :
                    val.specified ? val.value : null :
                null;
        };

        Expr = Sizzle.selectors = {

            // Can be adjusted by the user
            cacheLength: 50,

            createPseudo: markFunction,

            match: matchExpr,

            // IE6/7 return a modified href
            attrHandle: assertHrefNotNormalized ?
		{} :
		{
		    "href": function (elem) {
		        return elem.getAttribute("href", 2);
		    },
		    "type": function (elem) {
		        return elem.getAttribute("type");
		    }
		},

            find: {
                "ID": assertGetIdNotName ?
                    function (id, context, xml) {
                        if (typeof context.getElementById !== strundefined && !xml) {
                            var m = context.getElementById(id);
                            // Check parentNode to catch when Blackberry 4.6 returns
                            // nodes that are no longer in the document #6963
                            return m && m.parentNode ? [m] : [];
                        }
                    } :
                    function (id, context, xml) {
                        if (typeof context.getElementById !== strundefined && !xml) {
                            var m = context.getElementById(id);

                            return m ?
                                m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ?
                                    [m] :
                                undefined :
                                [];
                        }
                    },

                "TAG": assertTagNameNoComments ?
                    function (tag, context) {
                        if (typeof context.getElementsByTagName !== strundefined) {
                            return context.getElementsByTagName(tag);
                        }
                    } :
                    function (tag, context) {
                        var results = context.getElementsByTagName(tag);

                        // Filter out possible comments
                        if (tag === "*") {
                            var elem,
                                tmp = [],
                                i = 0;

                            for (; (elem = results[i]) ; i++) {
                                if (elem.nodeType === 1) {
                                    tmp.push(elem);
                                }
                            }

                            return tmp;
                        }
                        return results;
                    },

                "NAME": assertUsableName && function (tag, context) {
                    if (typeof context.getElementsByName !== strundefined) {
                        return context.getElementsByName(name);
                    }
                },

                "CLASS": assertUsableClassName && function (className, context, xml) {
                    if (typeof context.getElementsByClassName !== strundefined && !xml) {
                        return context.getElementsByClassName(className);
                    }
                }
            },

            relative: {
                ">": { dir: "parentNode", first: true },
                " ": { dir: "parentNode" },
                "+": { dir: "previousSibling", first: true },
                "~": { dir: "previousSibling" }
            },

            preFilter: {
                "ATTR": function (match) {
                    match[1] = match[1].replace(rbackslash, "");

                    // Move the given value to match[3] whether quoted or unquoted
                    match[3] = (match[4] || match[5] || "").replace(rbackslash, "");

                    if (match[2] === "~=") {
                        match[3] = " " + match[3] + " ";
                    }

                    return match.slice(0, 4);
                },

                "CHILD": function (match) {
                    /* matches from matchExpr["CHILD"]
                        1 type (only|nth|...)
                        2 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
                        3 xn-component of xn+y argument ([+-]?\d*n|)
                        4 sign of xn-component
                        5 x of xn-component
                        6 sign of y-component
                        7 y of y-component
                    */
                    match[1] = match[1].toLowerCase();

                    if (match[1] === "nth") {
                        // nth-child requires argument
                        if (!match[2]) {
                            Sizzle.error(match[0]);
                        }

                        // numeric x and y parameters for Expr.filter.CHILD
                        // remember that false/true cast respectively to 0/1
                        match[3] = +(match[3] ? match[4] + (match[5] || 1) : 2 * (match[2] === "even" || match[2] === "odd"));
                        match[4] = +((match[6] + match[7]) || match[2] === "odd");

                        // other types prohibit arguments
                    } else if (match[2]) {
                        Sizzle.error(match[0]);
                    }

                    return match;
                },

                "PSEUDO": function (match) {
                    var unquoted, excess;
                    if (matchExpr["CHILD"].test(match[0])) {
                        return null;
                    }

                    if (match[3]) {
                        match[2] = match[3];
                    } else if ((unquoted = match[4])) {
                        // Only check arguments that contain a pseudo
                        if (rpseudo.test(unquoted) &&
                            // Get excess from tokenize (recursively)
                            (excess = tokenize(unquoted, true)) &&
                            // advance to the next closing parenthesis
                            (excess = unquoted.indexOf(")", unquoted.length - excess) - unquoted.length)) {

                            // excess is a negative index
                            unquoted = unquoted.slice(0, excess);
                            match[0] = match[0].slice(0, excess);
                        }
                        match[2] = unquoted;
                    }

                    // Return only captures needed by the pseudo filter method (type and argument)
                    return match.slice(0, 3);
                }
            },

            filter: {
                "ID": assertGetIdNotName ?
                    function (id) {
                        id = id.replace(rbackslash, "");
                        return function (elem) {
                            return elem.getAttribute("id") === id;
                        };
                    } :
                    function (id) {
                        id = id.replace(rbackslash, "");
                        return function (elem) {
                            var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
                            return node && node.value === id;
                        };
                    },

                "TAG": function (nodeName) {
                    if (nodeName === "*") {
                        return function () { return true; };
                    }
                    nodeName = nodeName.replace(rbackslash, "").toLowerCase();

                    return function (elem) {
                        return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
                    };
                },

                "CLASS": function (className) {
                    var pattern = classCache[expando][className];
                    if (!pattern) {
                        pattern = classCache(className, new RegExp("(^|" + whitespace + ")" + className + "(" + whitespace + "|$)"));
                    }
                    return function (elem) {
                        return pattern.test(elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "");
                    };
                },

                "ATTR": function (name, operator, check) {
                    return function (elem, context) {
                        var result = Sizzle.attr(elem, name);

                        if (result == null) {
                            return operator === "!=";
                        }
                        if (!operator) {
                            return true;
                        }

                        result += "";

                        return operator === "=" ? result === check :
                            operator === "!=" ? result !== check :
                            operator === "^=" ? check && result.indexOf(check) === 0 :
                            operator === "*=" ? check && result.indexOf(check) > -1 :
                            operator === "$=" ? check && result.substr(result.length - check.length) === check :
                            operator === "~=" ? (" " + result + " ").indexOf(check) > -1 :
                            operator === "|=" ? result === check || result.substr(0, check.length + 1) === check + "-" :
                            false;
                    };
                },

                "CHILD": function (type, argument, first, last) {

                    if (type === "nth") {
                        return function (elem) {
                            var node, diff,
                                parent = elem.parentNode;

                            if (first === 1 && last === 0) {
                                return true;
                            }

                            if (parent) {
                                diff = 0;
                                for (node = parent.firstChild; node; node = node.nextSibling) {
                                    if (node.nodeType === 1) {
                                        diff++;
                                        if (elem === node) {
                                            break;
                                        }
                                    }
                                }
                            }

                            // Incorporate the offset (or cast to NaN), then check against cycle size
                            diff -= last;
                            return diff === first || (diff % first === 0 && diff / first >= 0);
                        };
                    }

                    return function (elem) {
                        var node = elem;

                        switch (type) {
                            case "only":
                            case "first":
                                while ((node = node.previousSibling)) {
                                    if (node.nodeType === 1) {
                                        return false;
                                    }
                                }

                                if (type === "first") {
                                    return true;
                                }

                                node = elem;

                                /* falls through */
                            case "last":
                                while ((node = node.nextSibling)) {
                                    if (node.nodeType === 1) {
                                        return false;
                                    }
                                }

                                return true;
                        }
                    };
                },

                "PSEUDO": function (pseudo, argument) {
                    // pseudo-class names are case-insensitive
                    // http://www.w3.org/TR/selectors/#pseudo-classes
                    // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
                    // Remember that setFilters inherits from pseudos
                    var args,
                        fn = Expr.pseudos[pseudo] || Expr.setFilters[pseudo.toLowerCase()] ||
                            Sizzle.error("unsupported pseudo: " + pseudo);

                    // The user may use createPseudo to indicate that
                    // arguments are needed to create the filter function
                    // just as Sizzle does
                    if (fn[expando]) {
                        return fn(argument);
                    }

                    // But maintain support for old signatures
                    if (fn.length > 1) {
                        args = [pseudo, pseudo, "", argument];
                        return Expr.setFilters.hasOwnProperty(pseudo.toLowerCase()) ?
                            markFunction(function (seed, matches) {
                                var idx,
                                    matched = fn(seed, argument),
                                    i = matched.length;
                                while (i--) {
                                    idx = indexOf.call(seed, matched[i]);
                                    seed[idx] = !(matches[idx] = matched[i]);
                                }
                            }) :
                            function (elem) {
                                return fn(elem, 0, args);
                            };
                    }

                    return fn;
                }
            },

            pseudos: {
                "not": markFunction(function (selector) {
                    // Trim the selector passed to compile
                    // to avoid treating leading and trailing
                    // spaces as combinators
                    var input = [],
                        results = [],
                        matcher = compile(selector.replace(rtrim, "$1"));

                    return matcher[expando] ?
                        markFunction(function (seed, matches, context, xml) {
                            var elem,
                                unmatched = matcher(seed, null, xml, []),
                                i = seed.length;

                            // Match elements unmatched by `matcher`
                            while (i--) {
                                if ((elem = unmatched[i])) {
                                    seed[i] = !(matches[i] = elem);
                                }
                            }
                        }) :
                        function (elem, context, xml) {
                            input[0] = elem;
                            matcher(input, null, xml, results);
                            return !results.pop();
                        };
                }),

                "has": markFunction(function (selector) {
                    return function (elem) {
                        return Sizzle(selector, elem).length > 0;
                    };
                }),

                "contains": markFunction(function (text) {
                    return function (elem) {
                        return (elem.textContent || elem.innerText || getText(elem)).indexOf(text) > -1;
                    };
                }),

                "enabled": function (elem) {
                    return elem.disabled === false;
                },

                "disabled": function (elem) {
                    return elem.disabled === true;
                },

                "checked": function (elem) {
                    // In CSS3, :checked should return both checked and selected elements
                    // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
                    var nodeName = elem.nodeName.toLowerCase();
                    return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
                },

                "selected": function (elem) {
                    // Accessing this property makes selected-by-default
                    // options in Safari work properly
                    if (elem.parentNode) {
                        elem.parentNode.selectedIndex;
                    }

                    return elem.selected === true;
                },

                "parent": function (elem) {
                    return !Expr.pseudos["empty"](elem);
                },

                "empty": function (elem) {
                    // http://www.w3.org/TR/selectors/#empty-pseudo
                    // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),
                    //   not comment, processing instructions, or others
                    // Thanks to Diego Perini for the nodeName shortcut
                    //   Greater than "@" means alpha characters (specifically not starting with "#" or "?")
                    var nodeType;
                    elem = elem.firstChild;
                    while (elem) {
                        if (elem.nodeName > "@" || (nodeType = elem.nodeType) === 3 || nodeType === 4) {
                            return false;
                        }
                        elem = elem.nextSibling;
                    }
                    return true;
                },

                "header": function (elem) {
                    return rheader.test(elem.nodeName);
                },

                "text": function (elem) {
                    var type, attr;
                    // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
                    // use getAttribute instead to test this case
                    return elem.nodeName.toLowerCase() === "input" &&
                        (type = elem.type) === "text" &&
                        ((attr = elem.getAttribute("type")) == null || attr.toLowerCase() === type);
                },

                // Input types
                "radio": createInputPseudo("radio"),
                "checkbox": createInputPseudo("checkbox"),
                "file": createInputPseudo("file"),
                "password": createInputPseudo("password"),
                "image": createInputPseudo("image"),

                "submit": createButtonPseudo("submit"),
                "reset": createButtonPseudo("reset"),

                "button": function (elem) {
                    var name = elem.nodeName.toLowerCase();
                    return name === "input" && elem.type === "button" || name === "button";
                },

                "input": function (elem) {
                    return rinputs.test(elem.nodeName);
                },

                "focus": function (elem) {
                    var doc = elem.ownerDocument;
                    return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus()) && !!(elem.type || elem.href);
                },

                "active": function (elem) {
                    return elem === elem.ownerDocument.activeElement;
                },

                // Positional types
                "first": createPositionalPseudo(function () {
                    return [0];
                }),

                "last": createPositionalPseudo(function (matchIndexes, length) {
                    return [length - 1];
                }),

                "eq": createPositionalPseudo(function (matchIndexes, length, argument) {
                    return [argument < 0 ? argument + length : argument];
                }),

                "even": createPositionalPseudo(function (matchIndexes, length) {
                    for (var i = 0; i < length; i += 2) {
                        matchIndexes.push(i);
                    }
                    return matchIndexes;
                }),

                "odd": createPositionalPseudo(function (matchIndexes, length) {
                    for (var i = 1; i < length; i += 2) {
                        matchIndexes.push(i);
                    }
                    return matchIndexes;
                }),

                "lt": createPositionalPseudo(function (matchIndexes, length, argument) {
                    for (var i = argument < 0 ? argument + length : argument; --i >= 0;) {
                        matchIndexes.push(i);
                    }
                    return matchIndexes;
                }),

                "gt": createPositionalPseudo(function (matchIndexes, length, argument) {
                    for (var i = argument < 0 ? argument + length : argument; ++i < length;) {
                        matchIndexes.push(i);
                    }
                    return matchIndexes;
                })
            }
        };

        function siblingCheck(a, b, ret) {
            if (a === b) {
                return ret;
            }

            var cur = a.nextSibling;

            while (cur) {
                if (cur === b) {
                    return -1;
                }

                cur = cur.nextSibling;
            }

            return 1;
        }

        sortOrder = docElem.compareDocumentPosition ?
            function (a, b) {
                if (a === b) {
                    hasDuplicate = true;
                    return 0;
                }

                return (!a.compareDocumentPosition || !b.compareDocumentPosition ?
                    a.compareDocumentPosition :
                    a.compareDocumentPosition(b) & 4
                ) ? -1 : 1;
            } :
            function (a, b) {
                // The nodes are identical, we can exit early
                if (a === b) {
                    hasDuplicate = true;
                    return 0;

                    // Fallback to using sourceIndex (in IE) if it's available on both nodes
                } else if (a.sourceIndex && b.sourceIndex) {
                    return a.sourceIndex - b.sourceIndex;
                }

                var al, bl,
                    ap = [],
                    bp = [],
                    aup = a.parentNode,
                    bup = b.parentNode,
                    cur = aup;

                // If the nodes are siblings (or identical) we can do a quick check
                if (aup === bup) {
                    return siblingCheck(a, b);

                    // If no parents were found then the nodes are disconnected
                } else if (!aup) {
                    return -1;

                } else if (!bup) {
                    return 1;
                }

                // Otherwise they're somewhere else in the tree so we need
                // to build up a full list of the parentNodes for comparison
                while (cur) {
                    ap.unshift(cur);
                    cur = cur.parentNode;
                }

                cur = bup;

                while (cur) {
                    bp.unshift(cur);
                    cur = cur.parentNode;
                }

                al = ap.length;
                bl = bp.length;

                // Start walking down the tree looking for a discrepancy
                for (var i = 0; i < al && i < bl; i++) {
                    if (ap[i] !== bp[i]) {
                        return siblingCheck(ap[i], bp[i]);
                    }
                }

                // We ended someplace up the tree so do a sibling check
                return i === al ?
                    siblingCheck(a, bp[i], -1) :
                    siblingCheck(ap[i], b, 1);
            };

        // Always assume the presence of duplicates if sort doesn't
        // pass them to our comparison function (as in Google Chrome).
        [0, 0].sort(sortOrder);
        baseHasDuplicate = !hasDuplicate;

        // Document sorting and removing duplicates
        Sizzle.uniqueSort = function (results) {
            var elem,
                i = 1;

            hasDuplicate = baseHasDuplicate;
            results.sort(sortOrder);

            if (hasDuplicate) {
                for (; (elem = results[i]) ; i++) {
                    if (elem === results[i - 1]) {
                        results.splice(i--, 1);
                    }
                }
            }

            return results;
        };

        Sizzle.error = function (msg) {
            throw new Error("Syntax error, unrecognized expression: " + msg);
        };

        function tokenize(selector, parseOnly) {
            var matched, match, tokens, type, soFar, groups, preFilters,
                cached = tokenCache[expando][selector];

            if (cached) {
                return parseOnly ? 0 : cached.slice(0);
            }

            soFar = selector;
            groups = [];
            preFilters = Expr.preFilter;

            while (soFar) {

                // Comma and first run
                if (!matched || (match = rcomma.exec(soFar))) {
                    if (match) {
                        // Don't consume trailing commas as valid
                        soFar = soFar.slice(match[0].length) || soFar;
                    }
                    groups.push(tokens = []);
                }

                matched = false;

                // Combinators
                if ((match = rcombinators.exec(soFar))) {
                    tokens.push(matched = new Token(match.shift()));
                    soFar = soFar.slice(matched.length);

                    // Cast descendant combinators to space
                    matched.type = match[0].replace(rtrim, " ");
                }

                // Filters
                for (type in Expr.filter) {
                    if ((match = matchExpr[type].exec(soFar)) && (!preFilters[type] ||
                        (match = preFilters[type](match)))) {

                        tokens.push(matched = new Token(match.shift()));
                        soFar = soFar.slice(matched.length);
                        matched.type = type;
                        matched.matches = match;
                    }
                }

                if (!matched) {
                    break;
                }
            }

            // Return the length of the invalid excess
            // if we're just parsing
            // Otherwise, throw an error or return tokens
            return parseOnly ?
                soFar.length :
                soFar ?
                    Sizzle.error(selector) :
                    // Cache the tokens
                    tokenCache(selector, groups).slice(0);
        }

        function addCombinator(matcher, combinator, base) {
            var dir = combinator.dir,
                checkNonElements = base && combinator.dir === "parentNode",
                doneName = done++;

            return combinator.first ?
                // Check against closest ancestor/preceding element
                function (elem, context, xml) {
                    while ((elem = elem[dir])) {
                        if (checkNonElements || elem.nodeType === 1) {
                            return matcher(elem, context, xml);
                        }
                    }
                } :

                // Check against all ancestor/preceding elements
                function (elem, context, xml) {
                    // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
                    if (!xml) {
                        var cache,
                            dirkey = dirruns + " " + doneName + " ",
                            cachedkey = dirkey + cachedruns;
                        while ((elem = elem[dir])) {
                            if (checkNonElements || elem.nodeType === 1) {
                                if ((cache = elem[expando]) === cachedkey) {
                                    return elem.sizset;
                                } else if (typeof cache === "string" && cache.indexOf(dirkey) === 0) {
                                    if (elem.sizset) {
                                        return elem;
                                    }
                                } else {
                                    elem[expando] = cachedkey;
                                    if (matcher(elem, context, xml)) {
                                        elem.sizset = true;
                                        return elem;
                                    }
                                    elem.sizset = false;
                                }
                            }
                        }
                    } else {
                        while ((elem = elem[dir])) {
                            if (checkNonElements || elem.nodeType === 1) {
                                if (matcher(elem, context, xml)) {
                                    return elem;
                                }
                            }
                        }
                    }
                };
        }

        function elementMatcher(matchers) {
            return matchers.length > 1 ?
                function (elem, context, xml) {
                    var i = matchers.length;
                    while (i--) {
                        if (!matchers[i](elem, context, xml)) {
                            return false;
                        }
                    }
                    return true;
                } :
                matchers[0];
        }

        function condense(unmatched, map, filter, context, xml) {
            var elem,
                newUnmatched = [],
                i = 0,
                len = unmatched.length,
                mapped = map != null;

            for (; i < len; i++) {
                if ((elem = unmatched[i])) {
                    if (!filter || filter(elem, context, xml)) {
                        newUnmatched.push(elem);
                        if (mapped) {
                            map.push(i);
                        }
                    }
                }
            }

            return newUnmatched;
        }

        function setMatcher(preFilter, selector, matcher, postFilter, postFinder, postSelector) {
            if (postFilter && !postFilter[expando]) {
                postFilter = setMatcher(postFilter);
            }
            if (postFinder && !postFinder[expando]) {
                postFinder = setMatcher(postFinder, postSelector);
            }
            return markFunction(function (seed, results, context, xml) {
                // Positional selectors apply to seed elements, so it is invalid to follow them with relative ones
                if (seed && postFinder) {
                    return;
                }

                var i, elem, postFilterIn,
                    preMap = [],
                    postMap = [],
                    preexisting = results.length,

                    // Get initial elements from seed or context
                    elems = seed || multipleContexts(selector || "*", context.nodeType ? [context] : context, [], seed),

                    // Prefilter to get matcher input, preserving a map for seed-results synchronization
                    matcherIn = preFilter && (seed || !selector) ?
                        condense(elems, preMap, preFilter, context, xml) :
                        elems,

                    matcherOut = matcher ?
                        // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
                        postFinder || (seed ? preFilter : preexisting || postFilter) ?

                            // ...intermediate processing is necessary
                            [] :

                            // ...otherwise use results directly
                    results :
                        matcherIn;

                // Find primary matches
                if (matcher) {
                    matcher(matcherIn, matcherOut, context, xml);
                }

                // Apply postFilter
                if (postFilter) {
                    postFilterIn = condense(matcherOut, postMap);
                    postFilter(postFilterIn, [], context, xml);

                    // Un-match failing elements by moving them back to matcherIn
                    i = postFilterIn.length;
                    while (i--) {
                        if ((elem = postFilterIn[i])) {
                            matcherOut[postMap[i]] = !(matcherIn[postMap[i]] = elem);
                        }
                    }
                }

                // Keep seed and results synchronized
                if (seed) {
                    // Ignore postFinder because it can't coexist with seed
                    i = preFilter && matcherOut.length;
                    while (i--) {
                        if ((elem = matcherOut[i])) {
                            seed[preMap[i]] = !(results[preMap[i]] = elem);
                        }
                    }
                } else {
                    matcherOut = condense(
                        matcherOut === results ?
                            matcherOut.splice(preexisting, matcherOut.length) :
                            matcherOut
                    );
                    if (postFinder) {
                        postFinder(null, results, matcherOut, xml);
                    } else {
                        push.apply(results, matcherOut);
                    }
                }
            });
        }

        function matcherFromTokens(tokens) {
            var checkContext, matcher, j,
                len = tokens.length,
                leadingRelative = Expr.relative[tokens[0].type],
                implicitRelative = leadingRelative || Expr.relative[" "],
                i = leadingRelative ? 1 : 0,

                // The foundational matcher ensures that elements are reachable from top-level context(s)
                matchContext = addCombinator(function (elem) {
                    return elem === checkContext;
                }, implicitRelative, true),
                matchAnyContext = addCombinator(function (elem) {
                    return indexOf.call(checkContext, elem) > -1;
                }, implicitRelative, true),
                matchers = [function (elem, context, xml) {
                    return (!leadingRelative && (xml || context !== outermostContext)) || (
                        (checkContext = context).nodeType ?
                            matchContext(elem, context, xml) :
                            matchAnyContext(elem, context, xml));
                }];

            for (; i < len; i++) {
                if ((matcher = Expr.relative[tokens[i].type])) {
                    matchers = [addCombinator(elementMatcher(matchers), matcher)];
                } else {
                    matcher = Expr.filter[tokens[i].type].apply(null, tokens[i].matches);

                    // Return special upon seeing a positional matcher
                    if (matcher[expando]) {
                        // Find the next relative operator (if any) for proper handling
                        j = ++i;
                        for (; j < len; j++) {
                            if (Expr.relative[tokens[j].type]) {
                                break;
                            }
                        }
                        return setMatcher(
                            i > 1 && elementMatcher(matchers),
                            i > 1 && tokens.slice(0, i - 1).join("").replace(rtrim, "$1"),
                            matcher,
                            i < j && matcherFromTokens(tokens.slice(i, j)),
                            j < len && matcherFromTokens((tokens = tokens.slice(j))),
                            j < len && tokens.join("")
                        );
                    }
                    matchers.push(matcher);
                }
            }

            return elementMatcher(matchers);
        }

        function matcherFromGroupMatchers(elementMatchers, setMatchers) {
            var bySet = setMatchers.length > 0,
                byElement = elementMatchers.length > 0,
                superMatcher = function (seed, context, xml, results, expandContext) {
                    var elem, j, matcher,
                        setMatched = [],
                        matchedCount = 0,
                        i = "0",
                        unmatched = seed && [],
                        outermost = expandContext != null,
                        contextBackup = outermostContext,
                        // We must always have either seed elements or context
                        elems = seed || byElement && Expr.find["TAG"]("*", expandContext && context.parentNode || context),
                        // Nested matchers should use non-integer dirruns
                        dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.E);

                    if (outermost) {
                        outermostContext = context !== document && context;
                        cachedruns = superMatcher.el;
                    }

                    // Add elements passing elementMatchers directly to results
                    for (; (elem = elems[i]) != null; i++) {
                        if (byElement && elem) {
                            for (j = 0; (matcher = elementMatchers[j]) ; j++) {
                                if (matcher(elem, context, xml)) {
                                    results.push(elem);
                                    break;
                                }
                            }
                            if (outermost) {
                                dirruns = dirrunsUnique;
                                cachedruns = ++superMatcher.el;
                            }
                        }

                        // Track unmatched elements for set filters
                        if (bySet) {
                            // They will have gone through all possible matchers
                            if ((elem = !matcher && elem)) {
                                matchedCount--;
                            }

                            // Lengthen the array for every element, matched or not
                            if (seed) {
                                unmatched.push(elem);
                            }
                        }
                    }

                    // Apply set filters to unmatched elements
                    matchedCount += i;
                    if (bySet && i !== matchedCount) {
                        for (j = 0; (matcher = setMatchers[j]) ; j++) {
                            matcher(unmatched, setMatched, context, xml);
                        }

                        if (seed) {
                            // Reintegrate element matches to eliminate the need for sorting
                            if (matchedCount > 0) {
                                while (i--) {
                                    if (!(unmatched[i] || setMatched[i])) {
                                        setMatched[i] = pop.call(results);
                                    }
                                }
                            }

                            // Discard index placeholder values to get only actual matches
                            setMatched = condense(setMatched);
                        }

                        // Add matches to results
                        push.apply(results, setMatched);

                        // Seedless set matches succeeding multiple successful matchers stipulate sorting
                        if (outermost && !seed && setMatched.length > 0 &&
                            (matchedCount + setMatchers.length) > 1) {

                            Sizzle.uniqueSort(results);
                        }
                    }

                    // Override manipulation of globals by nested matchers
                    if (outermost) {
                        dirruns = dirrunsUnique;
                        outermostContext = contextBackup;
                    }

                    return unmatched;
                };

            superMatcher.el = 0;
            return bySet ?
                markFunction(superMatcher) :
                superMatcher;
        }

        compile = Sizzle.compile = function (selector, group /* Internal Use Only */) {
            var i,
                setMatchers = [],
                elementMatchers = [],
                cached = compilerCache[expando][selector];

            if (!cached) {
                // Generate a function of recursive functions that can be used to check each element
                if (!group) {
                    group = tokenize(selector);
                }
                i = group.length;
                while (i--) {
                    cached = matcherFromTokens(group[i]);
                    if (cached[expando]) {
                        setMatchers.push(cached);
                    } else {
                        elementMatchers.push(cached);
                    }
                }

                // Cache the compiled function
                cached = compilerCache(selector, matcherFromGroupMatchers(elementMatchers, setMatchers));
            }
            return cached;
        };

        function multipleContexts(selector, contexts, results, seed) {
            var i = 0,
                len = contexts.length;
            for (; i < len; i++) {
                Sizzle(selector, contexts[i], results, seed);
            }
            return results;
        }

        function select(selector, context, results, seed, xml) {
            var i, tokens, token, type, find,
                match = tokenize(selector),
                j = match.length;

            if (!seed) {
                // Try to minimize operations if there is only one group
                if (match.length === 1) {

                    // Take a shortcut and set the context if the root selector is an ID
                    tokens = match[0] = match[0].slice(0);
                    if (tokens.length > 2 && (token = tokens[0]).type === "ID" &&
                            context.nodeType === 9 && !xml &&
                            Expr.relative[tokens[1].type]) {

                        context = Expr.find["ID"](token.matches[0].replace(rbackslash, ""), context, xml)[0];
                        if (!context) {
                            return results;
                        }

                        selector = selector.slice(tokens.shift().length);
                    }

                    // Fetch a seed set for right-to-left matching
                    for (i = matchExpr["POS"].test(selector) ? -1 : tokens.length - 1; i >= 0; i--) {
                        token = tokens[i];

                        // Abort if we hit a combinator
                        if (Expr.relative[(type = token.type)]) {
                            break;
                        }
                        if ((find = Expr.find[type])) {
                            // Search, expanding context for leading sibling combinators
                            if ((seed = find(
                                token.matches[0].replace(rbackslash, ""),
                                rsibling.test(tokens[0].type) && context.parentNode || context,
                                xml
                            ))) {

                                // If seed is empty or no tokens remain, we can return early
                                tokens.splice(i, 1);
                                selector = seed.length && tokens.join("");
                                if (!selector) {
                                    push.apply(results, slice.call(seed, 0));
                                    return results;
                                }

                                break;
                            }
                        }
                    }
                }
            }

            // Compile and execute a filtering function
            // Provide `match` to avoid retokenization if we modified the selector above
            compile(selector, match)(
                seed,
                context,
                xml,
                results,
                rsibling.test(selector)
            );
            return results;
        }

        if (document.querySelectorAll) {
            (function () {
                var disconnectedMatch,
                    oldSelect = select,
                    rescape = /'|\\/g,
                    rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,

                    // qSa(:focus) reports false when true (Chrome 21),
                    // A support test would require too much code (would include document ready)
                    rbuggyQSA = [":focus"],

                    // matchesSelector(:focus) reports false when true (Chrome 21),
                    // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
                    // A support test would require too much code (would include document ready)
                    // just skip matchesSelector for :active
                    rbuggyMatches = [":active", ":focus"],
                    matches = docElem.matchesSelector ||
                        docElem.mozMatchesSelector ||
                        docElem.webkitMatchesSelector ||
                        docElem.oMatchesSelector ||
                        docElem.msMatchesSelector;

                // Build QSA regex
                // Regex strategy adopted from Diego Perini
                assert(function (div) {
                    // Select is set to empty string on purpose
                    // This is to test IE's treatment of not explictly
                    // setting a boolean content attribute,
                    // since its presence should be enough
                    // http://bugs.jquery.com/ticket/12359
                    div.innerHTML = "<select><option selected=''></option></select>";

                    // IE8 - Some boolean attributes are not treated correctly
                    if (!div.querySelectorAll("[selected]").length) {
                        rbuggyQSA.push("\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)");
                    }

                    // Webkit/Opera - :checked should return selected option elements
                    // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
                    // IE8 throws error here (do not put tests after this one)
                    if (!div.querySelectorAll(":checked").length) {
                        rbuggyQSA.push(":checked");
                    }
                });

                assert(function (div) {

                    // Opera 10-12/IE9 - ^= $= *= and empty values
                    // Should not select anything
                    div.innerHTML = "<p test=''></p>";
                    if (div.querySelectorAll("[test^='']").length) {
                        rbuggyQSA.push("[*^$]=" + whitespace + "*(?:\"\"|'')");
                    }

                    // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
                    // IE8 throws error here (do not put tests after this one)
                    div.innerHTML = "<input type='hidden'/>";
                    if (!div.querySelectorAll(":enabled").length) {
                        rbuggyQSA.push(":enabled", ":disabled");
                    }
                });

                // rbuggyQSA always contains :focus, so no need for a length check
                rbuggyQSA = /* rbuggyQSA.length && */ new RegExp(rbuggyQSA.join("|"));

                select = function (selector, context, results, seed, xml) {
                    // Only use querySelectorAll when not filtering,
                    // when this is not xml,
                    // and when no QSA bugs apply
                    if (!seed && !xml && (!rbuggyQSA || !rbuggyQSA.test(selector))) {
                        var groups, i,
                            old = true,
                            nid = expando,
                            newContext = context,
                            newSelector = context.nodeType === 9 && selector;

                        // qSA works strangely on Element-rooted queries
                        // We can work around this by specifying an extra ID on the root
                        // and working up from there (Thanks to Andrew Dupont for the technique)
                        // IE 8 doesn't work on object elements
                        if (context.nodeType === 1 && context.nodeName.toLowerCase() !== "object") {
                            groups = tokenize(selector);

                            if ((old = context.getAttribute("id"))) {
                                nid = old.replace(rescape, "\\$&");
                            } else {
                                context.setAttribute("id", nid);
                            }
                            nid = "[id='" + nid + "'] ";

                            i = groups.length;
                            while (i--) {
                                groups[i] = nid + groups[i].join("");
                            }
                            newContext = rsibling.test(selector) && context.parentNode || context;
                            newSelector = groups.join(",");
                        }

                        if (newSelector) {
                            try {
                                push.apply(results, slice.call(newContext.querySelectorAll(
                                    newSelector
                                ), 0));
                                return results;
                            } catch (qsaError) {
                            } finally {
                                if (!old) {
                                    context.removeAttribute("id");
                                }
                            }
                        }
                    }

                    return oldSelect(selector, context, results, seed, xml);
                };

                if (matches) {
                    assert(function (div) {
                        // Check to see if it's possible to do matchesSelector
                        // on a disconnected node (IE 9)
                        disconnectedMatch = matches.call(div, "div");

                        // This should fail with an exception
                        // Gecko does not error, returns false instead
                        try {
                            matches.call(div, "[test!='']:sizzle");
                            rbuggyMatches.push("!=", pseudos);
                        } catch (e) { }
                    });

                    // rbuggyMatches always contains :active and :focus, so no need for a length check
                    rbuggyMatches = /* rbuggyMatches.length && */ new RegExp(rbuggyMatches.join("|"));

                    Sizzle.matchesSelector = function (elem, expr) {
                        // Make sure that attribute selectors are quoted
                        expr = expr.replace(rattributeQuotes, "='$1']");

                        // rbuggyMatches always contains :active, so no need for an existence check
                        if (!isXML(elem) && !rbuggyMatches.test(expr) && (!rbuggyQSA || !rbuggyQSA.test(expr))) {
                            try {
                                var ret = matches.call(elem, expr);

                                // IE 9's matchesSelector returns false on disconnected nodes
                                if (ret || disconnectedMatch ||
                                    // As well, disconnected nodes are said to be in a document
                                    // fragment in IE 9
                                        elem.document && elem.document.nodeType !== 11) {
                                    return ret;
                                }
                            } catch (e) { }
                        }

                        return Sizzle(expr, null, null, [elem]).length > 0;
                    };
                }
            })();
        }

        // Deprecated
        Expr.pseudos["nth"] = Expr.pseudos["eq"];

        // Back-compat
        function setFilters() { }
        Expr.filters = setFilters.prototype = Expr.pseudos;
        Expr.setFilters = new setFilters();

        // EXPOSE
        //if (typeof define === "function" && define.amd) {
        //    define(function () { return Sizzle; });
        //} else {
        //    window.Sizzle = Sizzle;
        //}
        return Sizzle;
    })();

    var ElemEvent = (function () {
        return {
            addEvent: function (elem, type, func) {
                if (elem.addEventListener) {
                    elem.addEventListener(type, func, false);
                } else if (elem.attachEvent) {
                    elem.attachEvent('on' + type, func);
                } else {
                    elem["on" + type] = func;
                }
                return this;
            },
            removeEvent: function (elem, type, func) {
                if (elem.removeEventListener) {
                    elem.removeEventListener(type, func, false);
                } else if (elem.attachEvent) {
                    elem.detachEvent('on' + type, func);
                } else {
                    elem["on" + type] = func;
                }
                return this;
            },
            event: function () {
                return event ? event : window.event;
            },
            target: function () {
                return event.target || event.srcElement;
            },
            preventDefault: function () {
                if (event.preventDefault) {
                    event.preventDefault;
                } else {
                    event.returnValue = false;
                }
            },
            stopPropagation: function (event) {
                if (event.stopProgation) {
                    event.stopProgation;
                } else {
                    event.cancalBubble = true;
                }
            },
            mousewheel: function (event, func) {
                var orgEvent = event || window.event, args = [].slice.call(arguments, 1), delta = 0, returnValue = true, deltaX = 0, deltaY = 0;
                event = orgEvent;
                event.type = "mousewheel";

                // Old school scrollwheel delta
                if (orgEvent.wheelDelta) { delta = orgEvent.wheelDelta / 120; }
                if (orgEvent.detail) { delta = -orgEvent.detail / 3; }

                // New school multidimensional scroll (touchpads) deltas
                deltaY = delta;

                // Gecko
                if (orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) {
                    deltaY = 0;
                    deltaX = -1 * delta;
                }

                // Webkit
                if (orgEvent.wheelDeltaY !== undefined) { deltaY = orgEvent.wheelDeltaY / 120; }
                if (orgEvent.wheelDeltaX !== undefined) { deltaX = -1 * orgEvent.wheelDeltaX / 120; }

                // Add event and delta to the front of the arguments
                args.unshift(event, delta, deltaX, deltaY);

                //return ($.event.dispatch || $.event.handle).apply(this, args);

                func(event, delta, deltaX, deltaY);
            }

        };
    })();

    var eventObj = {},
        eventArr = "blur change click dblclick error focus focusin focusout keydown keypress keyup mousedown mouseenter mouseleave mousemove mouseout mouseover mouseup resize scroll select submit unload DOMMouseScroll mousewheel".split(" ");
    for (var i = 0; i < eventArr.length; i++) {
        eventObj[eventArr[i]] = function (type) {
            return function (func) {
                for (var j = 0; j < Jx.fn.length; j++) {
                    ElemEvent.addEvent(Jx.fn[j], type, func);
                }
            };
        }(eventArr[i]);
    }

    var Jx = window[perfix] = (function () {
        /**!
        /* @name 查找符合条件的元素或集合
        /* Jx("#aa");
        /* Jx(".aa");
        /* Jx("input[name='aa']");
        /* Jx("input");
        /* Jx("input:first");
        /* Jx("div>input");
        /* @param {string|Jx} &selector #id|class|attr|target|限定符
        /* @param {string|Jx} &context #根节点
        /* @return {Jx} #Jx对象
        !*/
        var Jx = function (selector, context, results, seed) {
            return new Jx.fn.init(selector, context, results, seed);
        };

        Jx.fn = Jx.prototype = {
            constructor: Jx,
            init: function (selector, context, results, seed) {
                var i, elem = [];

                if (!selector) {
                    return this;
                }

                this.selector = selector;
                this.context = context;

                if (selector.nodeType) {
                    elem[0] = selector;
                }
                else if (typeof selector == "object") {
                    elem = selector;
                } else {
                    elem = Sizzle(selector, context, results, seed);
                }

                for (i = 0; i < elem.length; i++) {
                    this[i] = elem[i];
                }

                this.length = elem.length;

                elem = null;

                return this;
            },
            /**!
            /* @name 根据索引返回element对象
            /* Jx(".aa").get(0);
            /* @param {number} &num #对象索引
            /* @return {element} #返回1个节点元素
            !*/
            get: function (num) {
                return num == null ? this.toArray() : (num < 0 ? this[this.length + num] : this[num]);
            },
            /**!
            /* @name 设置或者获取元素对象的值,限定[:text,:password,textarea]
            /* Jx(".aa").val(111);写入
            /* Jx("#aa").val();获取
            /* @param {string} &value #值
            /* @return {string}
            !*/
            val: function (value) {
                if (typeof value == "undefined") {
                    if (this.length) {
                        return this[0].value;
                    }
                    return undefined;
                } else {
                    var i;
                    for (i = 0; i < this.length; i++) {
                        this[i].value = value;
                    }
                }
                return this;
            },
            attr: function (name, value) {
                if (typeof value === "undefined") {
                    if (this.length) {
                        return Sizzle.attr(this[0], name);
                    }
                    return undefined;
                } else {
                    var i;
                    for (i = 0; i < this.length; i++) {
                        this[i].setAttribute(name, value);
                    }
                }
                return this;
            },
            removeAttr: function (name) {
                var i;
                for (i = 0; i < this.length; i++) {
                    this[i].removeAttribute(name);
                }
                return this;
            },
            each: function (func) {
                if (func && this.length) {
                    var i, list = [];
                    for (i = 0; i < this.length; i++) {
                        list.push(this[i]);
                    }
                    for (i = 0; i < list.length; i++) {
                        func.call(list[i], i);
                    }
                    list = null;
                }
            },
            find: function (selector) {
                var i, j, elem, list = [];
                for (i = 0; i < this.length; i++) {
                    elem = Sizzle(selector, this[i]);
                    for (j = 0; j < elem.length; j++) {
                        list.push(elem[j]);
                    }
                }

                for (i = 0; i < list.length; i++) {
                    this[i] = list[i];
                }

                this.length = list.length;

                elem = null;
                list = null;

                return this;
            },
            on: function (type, func) {
                var i;
                for (i = 0; i < this.length; i++) {
                    if (type == "mousewheel") {
                        ElemEvent.addEvent(this[i], type, function (event) {
                            ElemEvent.mousewheel(event, func);
                        });
                    } else {
                        ElemEvent.addEvent(this[i], type, func);
                    }
                }
                return this;
            },
            off: function (type, func) {
                var i;
                for (i = 0; i < this.length; i++) {
                    ElemEvent.removeEvent(this[i], type, func);
                }
                return this;
            },
            css: function (attr, value) {
                if (typeof attr === 'string') {
                    if (value === undefined) {
                        return this[0].currentStyle ?
                            this[0].currentStyle[attr] : document.defaultView.getComputedStyle(this[0], false)[attr];
                    } else {
                        this[0].style[attr] = value;
                    };
                } else {
                    var i;
                    for (i = 0; i < this.length; i++) {
                        for (var a in attr) this[i].style[a] = attr[a];
                    }
                };

                return this;
            },
            width: function () {
                if (this.length) {
                    return this[0].offsetWidth;
                }

                return undefined;
            },
            height: function () {
                if (this.length) {
                    return this[0].offsetHeight;
                }

                return undefined;
            },
            show: function (display) {
                for (i = 0; i < this.length; i++) {
                    this[i].style.display = display || "";
                }
                return this;
            },
            hide: function () {
                for (i = 0; i < this.length; i++) {
                    this[i].style.display = "none";
                }
                return this;
            },
            hover: function (fn1, fn2) {
                var i;
                for (i = 0; i < this.length; i++) {
                    ElemEvent.addEvent(this[i], "mouseover", fn1).addEvent(this[i], "mouseout", fn2 || fn1);
                }
                return this;
            },
            focus: function (func) {
                if (this.length) {
                    this[0].focus();
                }
            },
            data: function (key, data) {
                if (!this.length) { return; }

                if (key && data) {
                    var i;
                    for (i = 0; i < this.length; i++) {
                        Jx.data(this[i], key, data);
                    }
                } else {
                    return Jx.data(this[0], key);
                }
            },
            html: function (value) {
                if (this.length) {
                    if (typeof value === "undefined") {
                        return this[0].innerHTML;
                    } else {
                        //异步插入html节点
                        function applyInnerHTML(HTML, func) {
                            var temp = document.createElement("div"),
                                frag = document.createDocumentFragment();
                            temp.innerHTML = HTML;

                            (function () {
                                if (temp.firstChild) {
                                    frag.appendChild(temp.firstChild)
                                    setTimeout(arguments.callee, 0);
                                } else {
                                    func(frag);
                                }
                            })();
                        };

                        var i;
                        for (i = 0; i < this.length; i++) {
                            this[i].innerHTML = "";
                            //有值才进行插入操作
                            value && applyInnerHTML(value, function (el) {
                                return function (frag) {
                                    el.appendChild(frag);
                                };
                            }(this[i]));
                        }
                    }
                }
                return this;
            },
            text: function (value) {
                if (this.length) {
                    if (typeof value === "undefined") {
                        return Sizzle.getText(this[0]);
                    } else {
                        var i;
                        for (i = 0; i < this.length; i++) {
                            this[i].innerText = value.replace(/<\/?[^>]+>/gi, "");
                        }
                    }
                }
                return this;
            },
            remove: function () {
                if (this.length) {
                    var i, isData;
                    for (i = 0; i < this.length; i++) {
                        if (this[i].nodeType == 1) {
                            isData = this[i].getAttribute("JxCache");
                            if (isData) {
                                Jx.removeData(this[i]);
                            }
                            this[i].parentNode.removeChild(this[i]);
                        }
                    }
                }
            },
            toArray: function () {
                if (this.length > 0) {
                    var i, c = [];
                    for (i = 0; i < this.length; i++) {
                        c.push(this[i]);
                    }
                    return c;
                }
                return undefined;
            },
            length: 0,
            size: function () {
                return this.length;
            },
            isJx: true
        };

        Jx.fn.init.prototype = Jx.fn;

        //------set perfix ------
        Jx.perfix = perfix;

        //--------Type-----------

        Jx.isFunction = function (obj) {
            return Jx.type(obj) === "function";
        };

        Jx.isArray = Array.isArray || function (obj) {
            return Jx.type(obj) === "array";
        };

        // A crude way of determining if an object is a window
        Jx.isWindow = function (obj) {
            return obj && typeof obj === "object" && "setInterval" in obj;
        }

        Jx.isNaN = function (obj) {
            return obj == null || !rdigit.test(obj) || isNaN(obj);
        };

        Jx.type = function (obj) {
            if (obj == undefined) return undefined;

            //isFinite 检查其参数是否是无穷大
            if (obj.$family) return (obj.$family.name == 'number' && !isFinite(obj)) ? false : obj.$family.name;

            if (obj.nodeName) {
                switch (obj.nodeType) {
                    case 1:
                        return 'element';
                    case 3:
                        return (/\S/).test(obj.nodeValue) ? 'textnode' : 'whitespace';
                }
            } else if (typeof obj.length == 'number') {
                if (obj.callee) return 'arguments'; else if (obj.item) return 'collection';
            }

            return obj == null ? String(obj) : Jx.class2type()[Object.prototype.toString.call(obj)] || "object";
        };

        Jx.isPlainObject = function (obj) {
            // Must be an Object.
            // Because of IE, we also have to check the presence of the constructor property.
            // Make sure that DOM nodes and window objects don't pass through, as well
            if (!obj || Jx.type(obj) !== "object" || obj.nodeType || Jx.isWindow(obj)) {
                return false;
            }

            // Not own constructor property must be Object
            if (obj.constructor &&
                !hasOwn.call(obj, "constructor") &&
                !hasOwn.call(obj.constructor.prototype, "isPrototypeOf")) {
                return false;
            }

            // Own properties are enumerated firstly, so to speed up,
            // if last one is own, then all properties are own.

            var key;
            for (key in obj) { }

            return key === undefined || hasOwn.call(obj, key);
        };

        Jx.isEmptyObject = function (obj) {
            for (var name in obj) {
                return false;
            }
            return true;
        };

        Jx.class2type = function () {
            var types = "Boolean Number String Function Array Date RegExp Object".split(" ");
            var oname = {};
            for (var i = 0; i < types.length; i++) {
                oname["[object " + types[i] + "]"] = types[i].toLowerCase();
            }
            return oname;
        };

        //--------Type End-----------
        Jx.extend = Jx.fn.extend = function () {
            var options, name, src, copy, copyIsArray, clone,
            target = arguments[0] || {},
            i = 1,
            length = arguments.length,
            deep = false;

            // Handle a deep copy situation
            if (typeof target === "boolean") {
                deep = target;
                target = arguments[1] || {};
                // skip the boolean and the target
                i = 2;
            }

            // Handle case when target is a string or something (possible in deep copy)
            if (typeof target !== "object" && !Jx.isFunction(target)) {
                target = {};
            }

            // extend jQuery itself if only one argument is passed
            if (length === i) {
                target = this;
                --i;
            }

            for (; i < length; i++) {
                // Only deal with non-null/undefined values
                if ((options = arguments[i]) != null) {
                    // Extend the base object
                    for (name in options) {
                        src = target[name];
                        copy = options[name];

                        // Prevent never-ending loop
                        if (target === copy) {
                            continue;
                        }

                        // Recurse if we're merging plain objects or arrays
                        if (deep && copy && (Jx.isPlainObject(copy) || (copyIsArray = Jx.isArray(copy)))) {
                            if (copyIsArray) {
                                copyIsArray = false;
                                clone = src && Jx.isArray(src) ? src : [];

                            } else {
                                clone = src && Jx.isPlainObject(src) ? src : {};
                            }

                            // Never move original objects, clone them
                            target[name] = Jx.extend(deep, clone, copy);

                            // Don't bring in undefined values
                        } else if (copy !== undefined) {
                            target[name] = copy;
                        }
                    }
                }
            }

            // Return the modified object
            return target;
        };

        //--------Event--------------
        Jx.fn.extend(eventObj);
        //--------Event End----------

        Jx.each = function (object, callback, args) {
            var name, i = 0,
                length = object.length,
                isObj = length === undefined || Jx.isFunction(object);

            if (args) {
                if (isObj) {
                    for (name in object) {
                        if (callback.apply(object[name], args) === false) {
                            break;
                        }
                    }
                } else {
                    for (; i < length;) {
                        if (callback.apply(object[i++], args) === false) {
                            break;
                        }
                    }
                }

                // A special, fast, case for the most common use of each
            } else {
                if (isObj) {
                    for (name in object) {
                        if (callback.call(object[name], name, object[name]) === false) {
                            break;
                        }
                    }
                } else {
                    for (; i < length;) {
                        if (callback.call(object[i], i, object[i++]) === false) {
                            break;
                        }
                    }
                }
            }

            return object;
        }

        Jx.extend({
            guid: 0,
            data: function (elem, key, data) {
                var pix = "JxCache";
                var ele = elem.isJx ? elem : Jx(elem);
                var id = ele.attr(pix);
                if (key && data) {
                    id = id || (pix + (this.guid += 1));
                    if (this.cache[id]) {
                        this.cache[id][key] = data;
                    } else {
                        this.cache[id] = {};
                        this.cache[id][key] = data;
                        ele.attr(pix, this.guid);
                    }
                    return this;

                } else if (key && id) {
                    id = pix + id;
                    if (this.cache[id]) {
                        return this.cache[id][key];
                    }
                }
                return undefined;
            },
            removeData: function (elem, key) {
                var pix = "JxCache";
                var ele = elem.isJx ? elem : Jx(elem);
                var id = pix + ele.attr(pix);
                if (typeof key === "undefined") {
                    delete this.cache[id];
                } else {
                    delete this.cache[id][key];
                }
            },
            cache: {}
        });

        return Jx;
    })();

    /**!
    /* @name Dom完成回调方法
    /* Jx.ready(function(){
    /*     document.getElementById("dom");
    /* });
    /* @param {function} &func #回调参数
    !*/
    Jx.ready = function (func) {
        var isTop, testDiv, scrollIntervalId,
       isBrowser = typeof window !== "undefined" && window.document,
       isPageLoaded = !isBrowser,
       doc = isBrowser ? document : null,
       readyCalls = [];

        function runCallbacks(callbacks) {
            var i;
            if (Jx.using.done() && !Jx.model.list.length) {
                for (i = 0; i < callbacks.length; i += 1) {
                    callbacks[i](doc);
                }
            } else {
                var timer = setInterval(function () {
                    if ((Jx.using.done() || Jx.using.filecheck >= 30) && !Jx.model.list.length) {
                        Jx.using.filecheck = 0;
                        clearInterval(timer);
                        for (i = 0; i < callbacks.length; i += 1) {
                            callbacks[i](doc);
                        }
                    }
                }, 30);
            }

        }

        function callReady() {
            var callbacks = readyCalls;

            if (isPageLoaded) {
                //Call the DOM ready callbacks
                if (callbacks.length) {
                    readyCalls = [];
                    runCallbacks(callbacks);
                }
            }
        }

        function pageLoaded() {
            if (!isPageLoaded) {
                isPageLoaded = true;
                if (scrollIntervalId) {
                    clearInterval(scrollIntervalId);
                }

                callReady();
            }
        }

        if (isBrowser) {
            if (document.addEventListener) {
                document.addEventListener("DOMContentLoaded", pageLoaded, false);
                window.addEventListener("load", pageLoaded, false);
            } else if (window.attachEvent) {
                window.attachEvent("onload", pageLoaded);

                testDiv = document.createElement('div');
                try {
                    isTop = window.frameElement === null;
                } catch (e) { }

                if (testDiv.doScroll && isTop && window.external) {
                    scrollIntervalId = setInterval(function () {
                        try {
                            testDiv.doScroll();
                            pageLoaded();
                        } catch (e) { }
                    }, 30);
                }
            }

            if (document.readyState === "complete") {
                pageLoaded();
            }
        }

        function domReady(callback) {
            if (isPageLoaded) {
                callback(doc);
            } else {
                readyCalls.push(callback);
            }
            return domReady;
        }

        domReady.version = '2.0.1';

        domReady.load = function (name, req, onLoad, config) {
            if (config.isBuild) {
                onLoad(null);
            } else {
                domReady(onLoad);
            }
        };

        /** END OF PUBLIC API **/

        domReady(func);
    };

    /**!
    /* @name 获取window,document的宽度和高度
    /* var page = Jx.page();
    /* page.pageWidth
    /* page.pageHeight
    /* page.windowWidth
    /* page.windowHeight
    /* @return {object} #pageWidth,pageHeight,windowWidth,windowHeight
    !*/
    Jx.page = function () {
        var xScroll, yScroll;
        if (window.innerHeight && window.scrollMaxY) {
            xScroll = window.innerWidth + window.scrollMaxX;
            yScroll = window.innerHeight + window.scrollMaxY;
        } else if (document.body.scrollHeight > document.body.offsetHeight) { // all but Explorer Mac
            xScroll = document.body.scrollWidth;
            yScroll = document.body.scrollHeight;
        } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
            xScroll = document.body.offsetWidth;
            yScroll = document.body.offsetHeight;
        }
        var windowWidth, windowHeight;
        if (self.innerHeight) {	// all except Explorer
            if (document.documentElement.clientWidth) {
                windowWidth = document.documentElement.clientWidth;
            } else {
                windowWidth = self.innerWidth;
            }
            windowHeight = self.innerHeight;
        } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
            windowWidth = document.documentElement.clientWidth;
            windowHeight = document.documentElement.clientHeight;
        } else if (document.body) { // other Explorers
            windowWidth = document.body.clientWidth;
            windowHeight = document.body.clientHeight;
        }
        // for small pages with total height less then height of the viewport
        if (yScroll < windowHeight) {
            pageHeight = windowHeight;
        } else {
            pageHeight = yScroll;
        }
        // for small pages with total width less then width of the viewport
        if (xScroll < windowWidth) {
            pageWidth = xScroll;
        } else {
            pageWidth = windowWidth;
        }

        return {
            pageWidth: pageWidth,
            pageHeight: pageHeight,
            windowWidth: windowWidth,
            windowHeight: windowHeight
        };
    };

    /**!
    /* @name 请求参数及中文编码
    /* Jx.param({aa:1,bb:2});
    /* 结果 "aa=1&bb=2";
    /* @param {object} &a #对象参数
    /* @return {string} #返回编码后的结果
    !*/
    Jx.param = function (a, traditional) {
        var s = [],
			add = function (key, value) {
			    // If value is a function, invoke it and return its value
			    value = Jx.isFunction(value) ? value() : value;
			    s[s.length] = encodeURIComponent(key) + "=" + encodeURIComponent(value);
			};

        // If an array was passed in, assume that it is an array of form elements.
        if (Jx.isArray(a) || (a.Jx && !Jx.isPlainObject(a))) {
            // Serialize the form elements
            Jx.each(a, function () {
                add(this.name, this.value);
            });

        } else {
            // If traditional, encode the "old" way (the way 1.3.2 or older
            // did it), otherwise encode params recursively.
            for (var prefix in a) {
                buildParams(prefix, a[prefix], traditional, add);
            }
        }

        function buildParams(prefix, obj, traditional, add) {
            if (Jx.isArray(obj)) {
                // Serialize array item.
                Jx.each(obj, function (i, v) {
                    if (traditional || /\[\]$/.test(prefix)) {
                        // Treat each array item as a scalar.
                        add(prefix, v);

                    } else {
                        // If array item is non-scalar (array or object), encode its
                        // numeric index to resolve deserialization ambiguity issues.
                        // Note that rack (as of 1.0.0) can't currently deserialize
                        // nested arrays properly, and attempting to do so may cause
                        // a server error. Possible fixes are to modify rack's
                        // deserialization algorithm or to provide an option or flag
                        // to force array serialization to be shallow.
                        buildParams(prefix + "[" + (typeof v === "object" ? i : "") + "]", v, traditional, add);
                    }
                });

            } else if (!traditional && Jx.type(obj) === "object") {
                // Serialize object item.
                for (var name in obj) {
                    buildParams(prefix + "[" + name + "]", obj[name], traditional, add);
                }

            } else {
                // Serialize scalar item.
                add(prefix, obj);
            }
        }

        // Return the resulting serialization
        return s.join("&").replace(/%20/g, "+");
    };

    /**!
    /* @name ajax异步请求
    /* Jx.ajax({
    /*     url: "/AjaxTest.ashx",
    /*     type:"get",
    /*     dataType: "json",
    /*     data: { aa: 2, cc: {bb:3,cc:4}},
    /*     error: function (data) {
    /*        
    /*     },
    /*     success: function (data) {
    /*         
    /*     }
    /* });
    /* @param {object} &options #配置对象
    !*/
    Jx.ajax = function (options) {

        var hastype = ("dataType" in options) ? true : false;

        //默认设置       
        options = {
            url: options.url || "",
            type: (options.type || "").toUpperCase() || "GET",
            dataType: (options.dataType || "").toLowerCase() || "xml",
            timeout: options.timeout || 50000,//超时连接,默认5秒
            delaytime: options.delaytime || 300,
            complete: options.complete || function () { },
            error: options.error || function () { },
            success: options.success || function () { },
            data: options.data || ""//服务器将会返回的数据类型
        };
        var xml = getXMLHttpRequest(options.dataType);

        //创建请求对象
        if (options.type == "GET" && options.data) {
            options.url = options.url + (options.url.indexOf("?") == -1 ? "?" : "&") + Jx.param(options.data);
        }
        xml.open(options.type, options.url);

        //初始化异步请求
        //超时计算 begin//
        var timeoutLength = options.timeout;

        var delaylength = options.delaytime;

        //我们在请求5秒超时后放弃请求
        var requestDone = false;
        //请求超过300毫秒（目前默认为300毫秒）则延时
        var isdelay = false;

        setTimeout(function () {
            //如果这个时候onreadystatechange回调函数已经执行请求已经返回，isdelay被该回调函数修改为null，否则设置isdelay=true说明系统已经开始延时
            if (isdelay == null)
                return;
            isdelay = true; //系统已经延时                 

            //记录请求是否完成，这个时候就要注意设置请求可能超时的定时监听了
            setTimeout(function () {
                requestDone = true;
            }, timeoutLength);

        }, delaylength);

        //超时计算 end//
        xml.onreadystatechange = function () {
            if (xml.readyState == 4 && !requestDone) {
                if (httpSuccess(xml)) {
                    var r_data = httpData(xml, options.dataType);
                    if (r_data != null)
                        options.success(r_data);
                    else
                        options.error(null);
                } else {
                    //否则就发生了错误
                    console.error(options.url + " 服务器响应失败！http状态为" + xml.status);
                    options.error();
                }
                options.complete();
                //调用完成回调函数
                xml = null;
                //为避免内存泄漏,清理文档
            }
        };

        if (options.type == "POST") {
            xml.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
        }
        xml.setRequestHeader("Accept", "*/*");
        xml.setRequestHeader("X-Requested-With", "XMLHttpRequest");

        xml.send((options.data && Jx.param(options.data)) || null);

        //发送请求,建立连接
        function httpSuccess(r) {
            try {
                //得不到服务器状态,而且我们正在请求本地文件,认为成功,200到300间的状态码表示成功      304未修改状态也酸成功    safari在文档为修改时返回空状态,,,
                return !r.status && location.protocol == "file:" || (r.status >= 200 && r.status < 300) || r.status == 304 || navigator.userAgent.indexOf("Safari") > 0 && typeof r.status == "undefined";
            }
            catch (e) { }

            return false;
            //若请求失败
        };
        function httpData(r, dataType) {
            //如果该方法返回null的话，则onsuccess回调函数不执行
            //组装返回的对象数据
            //抓去响应的http头部信息
            var ct = r.getResponseHeader("content-type");

            //检索返回是否为xml对象
            var data = ct && ct.indexOf("xml") >= 0;

            //alert(data)
            //如果用户设置要输出xml，只有在dataType参数为xml 并且是手动配置的xml才解析response
            data = (dataType == "xml" && hastype) || data ? r.responseXML : r.responseText;

            //因为ie不能解析responsexml
            if (((dataType == "xml" && hastype) || (ct && ct.indexOf("xml") >= 0)) && window.ActiveXObject) {
                //ie下面需要转换一下
                //data=r.responseText;
                var doc = new ActiveXObject("MSxml2.DOMDocument")
                doc.loadXML(r.responseText);
                data = doc;
                //避免内存泄漏，清理该文档
                doc = null;
            }

            //返回json对象
            if (dataType == "json") {
                try {
                    var resultData = (new Function("return" + data))();
                    if (resultData.result && resultData.result == -1) {
                        console.error(options.url + " " + resultData.msg)
                        return null;
                    } else {
                        return resultData;
                    }
                }
                catch (e) {
                    //json对象的数据结构错误，无法解析成对象
                    console.error(resultData + " " + e.message);
                    return null;
                }
            }

            //请求一个script脚本
            if (dataType == "script") {
                var scriptObj = document.createElement("script");
                scriptObj.nodeValue = data;
                scriptObj.setAttribute("charset", "utf-8");
                document.getElementsByTagName('head')[0].appendChild(scriptObj);
            }
            return data;
        };
        function getXMLHttpRequest(dataType) {
            var xmlHR = false;
            if (window.ActiveXObject) {
                try {
                    xmlHR = new ActiveXObject("Msxml2.XMLHTTP");
                }
                catch (e) {
                    try {
                        xmlHR = new ActiveXObject("Microsoft.XMLHTTP");
                    }
                    catch (e) {
                        try {
                            xmlHR = new ActiveXObject("Msxml2.XmlHttp.4.0");
                        } catch (e) { }
                    }
                }
            } else if (window.XMLHttpRequest) {
                xmlHR = new XMLHttpRequest();
                if (xmlHR.overrideMimeType) {
                    if (!hastype) {//如果没有传入dataType参数那么头定义为html的
                        xmlHR.overrideMimeType('text/xml');
                    } else {
                        switch (dataType) {
                            case "xml": xmlHR.overrideMimeType('text/xml');
                                break
                            case "json": xmlHR.overrideMimeType('text/json');
                                break
                            default: xmlHR.overrideMimeType('text/html');
                        }
                    }
                }
            }
            else {
                console.error("Create XMLHttpRequest object false");
                return false;
            }

            return xmlHR;
        }
    };

    /**!
    /* @name 创建带命名空间的全局对象
    /* Jx.namespace("A.B.C.D");//创建A.B.C.D这个{object}对象
    /* Jx.namespace("A.B.C.D",1);//创建A.B.C.D这个{数值}对象并且等于1
    /* Jx.namespace("A.B.C.D",{aa:1,bb:function(){ alert(1); } });//创建A.B.C.D这个{object}对象并且赋予属性及方法
    /* Jx.namespace("A.B.C.D",function(){ return 1; });//创建A.B.C.D这个{function}对象并且全局可调用
    /* 1. A.B.C.D = "temp";
    /* 2. alert(A.B.C.D) = 1;
    /* 3. alert(A.B.C.D.aa) = 1; A.B.C.D.bb();
    /* 4. A.B.C.D() 返回 1;
    /* @param {string} &name #命名空间
    /* @param {object} &objOrStr #初始化参数,可缺省
    !*/
    Jx.namespace = function (name, objOrStr) {
        var i, n, nameArr = name.split(".");
        for (i = 0; i < nameArr.length; i++) {
            if (!n) {
                n = window;
            }

            if (nameArr[i] in n) {
                if (nameArr.length - 1 == i && objOrStr) {
                    n[nameArr[i]] = objOrStr;
                } else {
                    n = n[nameArr[i]];
                }
            } else {
                if (nameArr.length - 1 == i && objOrStr) {
                    n[nameArr[i]] = objOrStr;
                } else {
                    n = n[nameArr[i]] = {};
                }
            }
        }
    };

    /*---------------------------应用扩展---------------------------*/

    /* Json类 */
    Jx.namespace(Jx.perfix + ".json.parse", function (data) {
        return (new Function("return (" + data + ")"))();
    });
    Jx.namespace(Jx.perfix + ".json.encode", (function () {
        /**
        * 字符串处理时需要转义的字符表
        * @private
        */
        var escapeMap = {
            "\b": '\\b',
            "\t": '\\t',
            "\n": '\\n',
            "\f": '\\f',
            "\r": '\\r',
            '"': '\\"',
            "\\": '\\\\'
        };

        /**
        * 字符串序列化
        * @private
        */
        function encodeString(source) {
            if (/["\\\x00-\x1f]/.test(source)) {
                source = source.replace(
                /["\\\x00-\x1f]/g,
                function (match) {
                    var c = escapeMap[match];
                    if (c) {
                        return c;
                    }
                    c = match.charCodeAt();
                    return "\\u00"
                            + Math.floor(c / 16).toString(16)
                            + (c % 16).toString(16);
                });
            }
            return '"' + source + '"';
        }

        /**
        * 数组序列化
        * @private
        */
        function encodeArray(source) {
            var result = ["["],
            l = source.length,
            preComma, i, item;

            for (i = 0; i < l; i++) {
                item = source[i];

                switch (typeof item) {
                    case "undefined":
                    case "function":
                    case "unknown":
                        break;
                    default:
                        if (preComma) {
                            result.push(',');
                        }
                        result.push(Jx.json.encode(item));
                        preComma = 1;
                }
            }
            result.push("]");
            return result.join("");
        }

        /**
        * 处理日期序列化时的补零
        * @private
        */
        function pad(source) {
            return source < 10 ? '0' + source : source;
        }

        /**
        * 日期序列化
        * @private
        */
        function encodeDate(source) {
            return '"' + source.getFullYear() + "-"
                + pad(source.getMonth() + 1) + "-"
                + pad(source.getDate()) + "T"
                + pad(source.getHours()) + ":"
                + pad(source.getMinutes()) + ":"
                + pad(source.getSeconds()) + '"';
        }

        return function (value) {
            switch (typeof value) {
                case 'undefined':
                    return 'undefined';

                case 'number':
                    return isFinite(value) ? String(value) : "null";

                case 'string':
                    return encodeString(value);

                case 'boolean':
                    return String(value);

                default:
                    if (value === null) {
                        return 'null';
                    } else if (value instanceof Array) {
                        return encodeArray(value);
                    } else if (value instanceof Date) {
                        return encodeDate(value);
                    } else {
                        var result = ['{'], encode = Jx.json.encode, preComma, item;

                        for (var key in value) {
                            if (Object.prototype.hasOwnProperty.call(value, key)) {
                                item = value[key];
                                switch (typeof item) {
                                    case 'undefined':
                                    case 'unknown':
                                    case 'function':
                                        break;
                                    default:
                                        if (preComma) {
                                            result.push(',');
                                        }
                                        preComma = 1;
                                        result.push(encode(key) + ':' + encode(item));
                                }
                            }
                        }
                        result.push('}');
                        return result.join('');
                    }
            }
        };
    })());

    /**!
    /* @name 异步加载JS类
    /* Jx.using("aa.js");加载aa.js 并在Jx.ready方法内可调用该js对象
    /* Jx.using("aa.js",function(){ test(); });加载aa.js 完成后可调用aa.js中的test()方法
    /* @param {string} &jsfile #js文件路径
    /* @param {function} &func #回调函数,js加载完成后执行,可缺省
    !*/
    Jx.namespace(Jx.perfix + ".using", function (jsfile, func) {
        if (Jx.using.fileMap[jsfile] == "done") {
            func && func();
            return;
        }

        if (Jx.using.fileMap[jsfile] == "wait") {
            if (func) {
                var check = 0;
                var timer = setInterval(function () {
                    if (Jx.using.fileMap[jsfile] == "done" || check >= 30) {
                        clearInterval(timer);
                        func();
                    }
                    check += 1;
                }, 50);
            }
            return;
        }

        Jx.using.fileMap[jsfile] = "wait";

        Jx.using.fileLoad(jsfile, func);
    });
    /**!
    /* @name Jx.using类配置需加载js的根目录,默认为/script/
    /* Jx.using.filebase = "/newJsDir/";将Jx.using.filebase定向为newJsDir这个目录
    /* @return {string} #js的根目录
    !*/
    Jx.namespace(Jx.perfix + ".using.filebase", "/script/");
    Jx.namespace(Jx.perfix + ".using.fileMap", {});
    Jx.namespace(Jx.perfix + ".using.filecheck", 0);
    Jx.namespace(Jx.perfix + ".using.done", function () {
        for (var item in Jx.using.fileMap) {
            if (Jx.using.fileMap[item] == "wait") {
                Jx.using.filecheck += 1;
                return false;
            }
        }
        return true;
    });
    Jx.namespace(Jx.perfix + ".using.fileLoad", function (jsfile, func) {
        var head = document.getElementsByTagName('head')[0],
        script = document.createElement("script");
        script.type = 'text/javascript';
        if (jsfile.indexOf("http") != -1 || jsfile.indexOf("/") == 0) {
            script.src = jsfile;
        } else {
            script.src = Jx.using.filebase + jsfile + ".js";
        }
        script.charset = 'utf-8';
        script.onreadystatechange = script.onload = function () {
            if (!script.readyState || script.readyState === "complete" || script.readyState === "loaded") {
                Jx.using.fileMap[jsfile] = "done";
                script.onload = script.onreadystatechange = script.onerror = null;
                func && func();
            }
        };
        script.onerror = function (e) {
            script.onload = script.onreadystatechange = script.onerror = null;
            throw new Error(jsfile + " failed to load.");
        };
        head.insertBefore(script, head.firstChild);
    });

    /**!
    /* @name Jx.model类 定义模块
    !*/
    Jx.namespace(Jx.perfix + ".model", function (modelname, func) {

        Jx.model.list.push(modelname);

        if (Jx.using.done()) {
            Jx.namespace(modelname, func());
            Jx.model.list.shift();
        } else {
            var timer = setInterval(function () {
                if (Jx.using.done()) {
                    clearInterval(timer);
                    Jx.namespace(modelname, func());
                    Jx.model.list.shift();
                }
            }, 10);
        }
    });
    Jx.namespace(Jx.perfix + ".model.list", []);


})(window, undefined, "Jx");